# -*- coding: utf-8 -*-

import logging

from socketio.namespace import BaseNamespace
from socketio.mixins import RoomsMixin, BroadcastMixin
from socketio.sdjango import namespace
from game.models import *
from django.contrib.auth.models import User

import pdb

#user_auxiliar = User.objects.get(username="root")
user_auxiliar = User.objects.all()
if user_auxiliar:
    user_auxiliar = user_auxiliar[0]

@namespace('/chatt')
class ChatNamespace(BaseNamespace, RoomsMixin, BroadcastMixin):
    nicknames = []

    def initialize(self):
        self.logger = logging.getLogger("socketio.chat")
        self.log("Socketio session CHAT started")
        
    def log(self, message):
        self.logger.info("[{0}] {1}".format(self.socket.sessid, message))
    
    def on_join(self, room):
        self.room = room
        self.join(room)
        return True
        
    def on_nickname(self, nickname):
        self.log('Nickname: {0}'.format(nickname))
        self.nicknames.append(nickname)
        self.socket.session['nickname'] = nickname
        self.broadcast_event('announcement', '%s has connected' % nickname)
        self.broadcast_event('nicknames', self.nicknames)
        return True, nickname

    def recv_disconnect(self):
        # Remove nickname from the list.
        self.log('Chat Disconnected')
        nickname = self.socket.session['nickname']
        self.nicknames.remove(nickname)
        self.broadcast_event('announcement', '%s has disconnected' % nickname)
        self.broadcast_event('nicknames', self.nicknames)
        self.disconnect(silent=True)
        return True

    def on_user_message(self, msg):
        self.log('User message: {0}'.format(msg))
        self.emit_to_room(self.room, 'msg_to_room',
            self.socket.session['nickname'], msg)
        return True



class GamesMixin(object):
    def __init__(self, *args, **kwargs):
        super(GamesMixin, self).__init__(*args, **kwargs)
        if 'games' not in self.session:
            self.session['games'] = set()  # a set of simple strings

    def join(self, game):
        """Lets a user join a room on a specific Namespace."""
        self.session['games'].add(self._get_game_name(game))

    def leave(self, game):
        """Lets a user leave a room on a specific Namespace."""
        self.session['games'].remove(self._get_game_name(game))

    def _get_game_name(self, game):
        return self.ns_name + '_' + game
        # implementar, no entiendo
        
    def emit_to_game(self, game, event, *args):
        """This is sent to all in the room (in this particular Namespace)"""
        pkt = dict(type="event",
                   name=event,
                   args=args,
                   endpoint=self.ns_name)
        game_name = self._get_game_name(game)
        for sessid, socket in self.socket.server.sockets.iteritems():
            if 'games' not in socket.session:
                continue
            if game_name in socket.session['games'] and self.socket != socket:
                socket.send_packet(pkt)


@namespace('/gamee')
class GameNamespace(BaseNamespace, GamesMixin, BroadcastMixin):
    players = [] # Puede ser una lista de Players..

    def on_new_ant(self, type_ant):
        self.log('#{1} for player {0}'.format(self.socket.session['nickname'], type_ant))
        player = Player.objects.get(id=self.socket.session['player'])
        try:
            a = Ant(type_ant=type_ant, base=player.base, player=player, position='C')
            a.save()
            # eliminar recursos del jugador
            # comprobar que no sobrepase un máximo
            # se puede hacer en el save de Ant...


        except Exception: #vigilar el tipo de exception
            #self.emit_error_new_ant....()
            self.log("problemas al crear la hormiga")
            return False # puedes superar el número máximo de hormigas asociadas a un mismo player...


        #emite una estadística global, nunca el número de hormigas exactas...
        #players_points = [ p.get_growth_statistics() for p in self.players ]
        #players_names = [ p.name for p in self.players ]
        # hacerlo en una línea más eficiente...
        players_points = []
        players_names = []
        for p in self.players:
            player = Player.objects.get(id=p)
            players_points.append(player.get_growth_statistics())
            players_names.append(player.name)
        self.broadcast_event('players', players_names, players_points)
        #self.emit_ants_to_game(self.game, ) #Game

        # Actualización individual de recursos
        pkt = dict(type="event", name='resources', args=(player.resources,), endpoint=self.ns_name)
        self.socket.send_packet(pkt)

        # Actualización individual del ejército
        # Encapsular en funciones...

        num_ants = ()
        type_ants = ()
        num = player.ants_player.filter(type_ant='W').count()
        num_ants = num_ants + (num, )
        type_ants = type_ants + ('W', )
        
        num = player.ants_player.filter(type_ant='OD').count()
        num_ants = num_ants + (num, )
        type_ants = type_ants + ('OD', )

        num = player.ants_player.filter(type_ant='OO').count()
        num_ants = num_ants + (num, )
        type_ants = type_ants + ('OO', )

        num = player.ants_player.filter(type_ant='FD').count()
        num_ants = num_ants + (num, )
        type_ants = type_ants + ('FD', )

        num = player.ants_player.filter(type_ant='FO').count()
        num_ants = num_ants + (num, )
        type_ants = type_ants + ('FO', )

        num = player.ants_player.filter(type_ant='Q').count()
        num_ants = num_ants + (num, )
        type_ants = type_ants + ('Q', )

        pkt = dict(type="event", name='ants', args=(type_ants, num_ants, ), endpoint=self.ns_name)
        self.socket.send_packet(pkt)


        return True

    def initialize(self):
        self.logger = logging.getLogger("socketio.ant")
        self.log("Socketio session GAME started")

    def log(self, message):
        self.logger.info("[{0}] {1}".format(self.socket.sessid, message))

    def on_join(self, game):
        self.game = game
        self.join(game)
        return True

    def on_nickname(self, nickname):
        #Podemos poner un límite.
        #Cada vez que entre algún cliente nuevo actualizaremos al cliente el listado de jugadores.

        g = Game.objects.get(id=self.game)
        b = Base(game=g, x_coordinate = 5, y_coordinate=5, type_base='P')
        b.save()
        player = Player(name=nickname, user_profile=user_auxiliar, base=b, game=g)
        player.save()

        self.players.append(player.id) # asociar al game, hasta un límite
        self.log('New player connected, Nickname: {0}'.format(nickname))

        self.socket.session['player'] = object()
        self.socket.session['player'] = player.id
        #self.broadcast_event('announcement', '%s has connected' % player.name)

        # hacerlo en una línea más eficiente...
        players_points = []
        players_names = []
        for p in self.players:
            player = Player.objects.get(id=p)
            players_points.append(player.get_growth_statistics())
            players_names.append(player.name)

        #players_points = [ Player.objects.get(id=p).get_growth_statistics() for p in self.players ]
        #players_names = [ p.name for p in self.players ]

        self.broadcast_event('players', players_names, players_points)

        # Actualización individual de recursos
        pkt = dict(type="event", name='resources', args=(player.resources,), endpoint=self.ns_name)
        self.socket.send_packet(pkt)


        return True
        #return True, player

    """
    def recv_connect(self):

        self.log('New Player Connected')
        # asociar al game, hasta un límite
        nickname = self.socket.session['nickname']
        self.broadcast_event('announcement', '%s has connected' % nickname)
        self.broadcast_event('nicknames', self.nicknames)
        return True
    """
    def recv_disconnect(self):
        # Remove nickname from the list.
        self.log('Player Disconnected')
        if 'player' in self.session:
            player = Player.objects.get(id=self.socket.session['player'])
            self.players.remove(player)
            player.remove()
        #self.broadcast_event('announcement', '%s has disconnected' % player.nickname)

        #players_points = [ p.get_growth_statistics() for p in self.players ]
        #players_names = [ p.name for p in self.players ]

        # hacerlo en una línea más eficiente...
        players_points = []
        players_names = []
        for p in self.players:
            player = Player.objects.get(id=p)
            players_points.append(player.get_growth_statistics())
            players_names.append(player.name)

        self.broadcast_event('players', players_names, players_points)
        self.disconnect(silent=True)
        return True

